package demoMod.strongerheart.monsters;

import basemod.ReflectionHacks;
import com.badlogic.gdx.graphics.Color;
import com.esotericsoftware.spine.AnimationState;
import com.megacrit.cardcrawl.actions.AbstractGameAction;
import com.megacrit.cardcrawl.actions.ClearCardQueueAction;
import com.megacrit.cardcrawl.actions.GameActionManager;
import com.megacrit.cardcrawl.actions.animations.VFXAction;
import com.megacrit.cardcrawl.actions.common.*;
import com.megacrit.cardcrawl.cards.DamageInfo;
import com.megacrit.cardcrawl.cards.status.Slimed;
import com.megacrit.cardcrawl.core.CardCrawlGame;
import com.megacrit.cardcrawl.core.Settings;
import com.megacrit.cardcrawl.dungeons.AbstractDungeon;
import com.megacrit.cardcrawl.localization.MonsterStrings;
import com.megacrit.cardcrawl.monsters.AbstractMonster;
import com.megacrit.cardcrawl.powers.*;
import com.megacrit.cardcrawl.relics.AbstractRelic;
import com.megacrit.cardcrawl.unlock.UnlockTracker;
import com.megacrit.cardcrawl.vfx.BorderFlashEffect;
import com.megacrit.cardcrawl.vfx.combat.BloodShotEffect;
import com.megacrit.cardcrawl.vfx.combat.HeartBuffEffect;
import com.megacrit.cardcrawl.vfx.combat.HeartMegaDebuffEffect;
import com.megacrit.cardcrawl.vfx.combat.ViceCrushEffect;
import demoMod.strongerheart.StrongerHeartMod;
import demoMod.strongerheart.powers.BeatOfLifePower;
import demoMod.strongerheart.powers.InfinityCursePower;
import demoMod.strongerheart.powers.ShadowPower;

public class StrongerHeart extends AbstractMonster {
    public static final String ID = StrongerHeartMod.makeID("StrongerHeart");
    private static final MonsterStrings monsterStrings = CardCrawlGame.languagePack.getMonsterStrings(ID);

    public static final String NAME = monsterStrings.NAME;
    public static final String[] MOVES = monsterStrings.MOVES;
    public static final String[] DIALOG = monsterStrings.DIALOG;

    private InvinciblePower invinciblePower;

    private int phase = 1;
    private boolean enhancePhase3 = false;
    private int phase3AttackAmount = 8;
    private int turns = 0;

    public StrongerHeart() {
        super(NAME, ID, 150, 30.0F, -30.0F, 476.0F, 410.0F, null, -50.0F, 30.0F);
        this.loadAnimation("images/npcs/heart/skeleton.atlas", "images/npcs/heart/skeleton.json", 1.0F);
        AnimationState.TrackEntry e = this.state.setAnimation(0, "idle", true);
        e.setTimeScale(1.5F);
        this.type = EnemyType.BOSS;
        if (AbstractDungeon.ascensionLevel >= 9) {
            this.setHp(150);
        } else {
            this.setHp(135);
        }

        if (AbstractDungeon.ascensionLevel >= 4) {
            if (AbstractDungeon.ascensionLevel < 19) {
                this.damage.add(new DamageInfo(this, 50));
            } else {
                this.damage.add(new DamageInfo(this, 5));
                phase3AttackAmount++;
            }

            this.damage.add(new DamageInfo(this, 55));
            this.damage.add(new DamageInfo(this, 11));

            this.damage.add(new DamageInfo(this, 22));
            this.damage.add(new DamageInfo(this, 1));
        } else {
            this.damage.add(new DamageInfo(this, 45)); //一形态重击吸血 0

            this.damage.add(new DamageInfo(this, 50)); //二形态重击 1
            this.damage.add(new DamageInfo(this, 10)); //二形态多段吸血 2

            this.damage.add(new DamageInfo(this, 20)); //三形态重击 3
            this.damage.add(new DamageInfo(this, 1)); //三形态多段 4
        }
    }

    @Override
    public void usePreBattleAction() {
        CardCrawlGame.music.unsilenceBGM();
        AbstractDungeon.scene.fadeOutAmbiance();
        AbstractDungeon.getCurrRoom().playBgmInstantly("BOSS_ENDING");
        int invincibleAmt = 100;

        invinciblePower = new InvinciblePower(this, invincibleAmt);
        addToBot(new ApplyPowerAction(this, this, invinciblePower));
        addToBot(new ApplyPowerAction(this, this, new InfinityCursePower(this, 3, 4)));

        AbstractDungeon.getCurrRoom().cannotLose = true;
    }

    @Override
    public void damage(DamageInfo info) {
        if (info.output > 0 && this.hasPower(IntangiblePower.POWER_ID)) {
            info.output = 1;
        }
        super.damage(info);
        if (this.currentHealth <= 0 && !this.halfDead) {
            if (AbstractDungeon.getCurrRoom().cannotLose) {
                this.halfDead = true;
            }

            for (AbstractPower power : powers) {
                power.onDeath();
            }

            for (AbstractRelic relic : AbstractDungeon.player.relics) {
                relic.onMonsterDeath(this);
            }

            addToTop(new ClearCardQueueAction());

            powers.removeIf(power -> power instanceof StrengthPower && power.amount <= 0);

            this.setMove((byte)0, Intent.UNKNOWN);
            this.createIntent();
            applyPowers();
            phase++;
            addToBot(new AbstractGameAction() {
                @Override
                public void update() {
                    if (phase == 3) {
                        takeTurn();
                        setMove((byte)8, Intent.ATTACK_BUFF, damage.get(3).base);
                        createIntent();
                        AbstractDungeon.getCurrRoom().cannotLose = false;
                    }
                    isDone = true;
                }
            });

            if (GameActionManager.turn <= 1) {
                UnlockTracker.unlockAchievement("YOU_ARE_NOTHING");
            }
        }
    }

    @Override
    public void takeTurn() {
        switch (this.nextMove) {
            case 0: //复活，进入下一阶段 UNKNOWN
                addToBot(new VFXAction(new BorderFlashEffect(new Color(0.8F, 0.5F, 1.0F, 1.0F))));
                addToBot(new VFXAction(new HeartBuffEffect(this.hb.cX, this.hb.cY)));
                switch (this.phase) {
                    case 2:
                        if (AbstractDungeon.ascensionLevel >= 9) {
                            this.maxHealth = 320;
                        } else {
                            this.maxHealth = 300;
                        }
                        invinciblePower.amount = 250;
                        ReflectionHacks.setPrivate(invinciblePower, InvinciblePower.class, "maxAmt", 250);
                        invinciblePower.updateDescription();
                        break;
                    case 3:
                    default:
                        if (AbstractDungeon.ascensionLevel >= 9) {
                            this.maxHealth = 100;
                        } else {
                            this.maxHealth = 90;
                        }
                        powers.removeIf(power -> power instanceof InfinityCursePower);
                        powers.removeIf(power -> power instanceof InvinciblePower);
                        IntangiblePower power = new IntangiblePower(this, 1);
                        ReflectionHacks.setPrivate(power, IntangiblePower.class, "justApplied", false);
                        addToBot(new ApplyPowerAction(this, this, power));
                        if (enhancePhase3) {
                            addToBot(new ApplyPowerAction(this, this, new RitualPower(this, 1, false)));
                        }
                        addToBot(new ApplyPowerAction(this, this, new RitualPower(this, 1, false)));
                        addToBot(new ApplyPowerAction(this, this, new ShadowPower(this, AbstractDungeon.ascensionLevel >= 19 ? 3 : 2)));
                        addToBot(new ApplyPowerAction(this, this, new BeatOfLifePower(this, AbstractDungeon.ascensionLevel >= 19 ? 2 : 1)));
                }
                this.halfDead = false;
                addToBot(new HealAction(this, this, this.maxHealth));
                if (phase == 3) {
                    return; //不重新roll意图
                }
                break;
            case 1: //强化，进入下一阶段 BUFF
                addToBot(new VFXAction(new BorderFlashEffect(new Color(0.8F, 0.5F, 1.0F, 1.0F))));
                addToBot(new VFXAction(new HeartBuffEffect(this.hb.cX, this.hb.cY)));
                switch (this.phase) {
                    case 1:
                        this.enhancePhase3 = true;
                        if (AbstractDungeon.ascensionLevel >= 9) {
                            this.maxHealth = 320;
                        } else {
                            this.maxHealth = 300;
                        }
                        addToBot(new AbstractGameAction() {
                            @Override
                            public void update() {
                                increaseMaxHp(3 * currentHealth, true);
                                isDone = true;
                            }
                        });
                        invinciblePower.amount = 250;
                        ReflectionHacks.setPrivate(invinciblePower, InvinciblePower.class, "maxAmt", 250);
                        invinciblePower.updateDescription();
                        addToBot(new ApplyPowerAction(this, this, new IntangiblePower(this, 1)));
                        break;
                    case 2:
                    default:
                        if (enhancePhase3) {
                            addToBot(new ApplyPowerAction(this, this, new IntangiblePower(this, 1)));
                            addToBot(new ApplyPowerAction(this, this, new RitualPower(this, 1, false)));
                        }
                        int intAmount = this.currentHealth / 100;
                        if (intAmount > 0) {
                            addToBot(new ApplyPowerAction(this, this, new IntangiblePower(this, intAmount)));
                        }
                        addToBot(new ApplyPowerAction(this, this, new IntangiblePower(this, 2)));
                        addToBot(new ApplyPowerAction(this, this, new RitualPower(this, 3, false)));
                        if (AbstractDungeon.ascensionLevel >= 9) {
                            this.maxHealth = 100;
                        } else {
                            this.maxHealth = 90;
                        }
                        powers.removeIf(power -> power instanceof InfinityCursePower);
                        powers.removeIf(power -> power instanceof InvinciblePower);
                        addToBot(new ApplyPowerAction(this, this, new ShadowPower(this, AbstractDungeon.ascensionLevel >= 19 ? 3 : 2)));
                        addToBot(new ApplyPowerAction(this, this, new BeatOfLifePower(this, AbstractDungeon.ascensionLevel >= 19 ? 2 : 1)));
                        AbstractDungeon.getCurrRoom().cannotLose = false;
                }
                addToBot(new HealAction(this, this, this.maxHealth));
                phase++;
                break;
            case 2: //一形态重击/多段并吸血 ATTACK_BUFF
                if (AbstractDungeon.ascensionLevel < 19) {
                    addToBot(new VFXAction(new ViceCrushEffect(AbstractDungeon.player.hb.cX, AbstractDungeon.player.hb.cY), 0.5F));
                    addToBot(new DamageAction(AbstractDungeon.player, this.damage.get(0), AbstractGameAction.AttackEffect.BLUNT_HEAVY));
                    addToBot(new HealAction(this, this, AbstractDungeon.player.lastDamageTaken * 2));
                } else {
                    if (Settings.FAST_MODE) {
                        AbstractDungeon.actionManager.addToBottom(new VFXAction(new BloodShotEffect(this.hb.cX, this.hb.cY, AbstractDungeon.player.hb.cX, AbstractDungeon.player.hb.cY, 11), 0.25F));
                    } else {
                        AbstractDungeon.actionManager.addToBottom(new VFXAction(new BloodShotEffect(this.hb.cX, this.hb.cY, AbstractDungeon.player.hb.cX, AbstractDungeon.player.hb.cY, 11), 0.6F));
                    }
                    for (int i=0;i<10;i++) {
                        addToBot(new DamageAction(AbstractDungeon.player, this.damage.get(0), AbstractGameAction.AttackEffect.BLUNT_HEAVY, true));
                        addToBot(new AbstractGameAction() {
                            @Override
                            public void update() {
                                addToTop(new HealAction(StrongerHeart.this, StrongerHeart.this, AbstractDungeon.player.lastDamageTaken * 3));
                                isDone = true;
                            }
                        });
                    }
                }
                break;
            case 3: //一阶段塞牌 DEBUFF
                addToBot(new MakeTempCardInDrawPileAction(new Slimed(), 4, true, true));
                addToBot(new MakeTempCardInDiscardAction(new Slimed(), 2));
                break;
            case 4: //二形态上debuff STRONG_DEBUFF
                addToBot(new VFXAction(new HeartMegaDebuffEffect()));
                addToBot(new ApplyPowerAction(AbstractDungeon.player, this, new VulnerablePower(AbstractDungeon.player, 2, true), 3));
                addToBot(new ApplyPowerAction(AbstractDungeon.player, this, new WeakPower(AbstractDungeon.player, 2, true), 3));
                if (AbstractDungeon.ascensionLevel >= 19) {
                    addToBot(new ApplyPowerAction(AbstractDungeon.player, this, new FrailPower(AbstractDungeon.player, 2, true), 2));
                }
                break;
            case 5: //二形态上盾 DEFEND
                addToBot(new GainBlockAction(this, this, AbstractDungeon.ascensionLevel >= 19 ? 111 : 99));
                break;
            case 6: //二形态重击 ATTACK
                addToBot(new VFXAction(new ViceCrushEffect(AbstractDungeon.player.hb.cX, AbstractDungeon.player.hb.cY), 0.5F));
                addToBot(new DamageAction(AbstractDungeon.player, this.damage.get(1), AbstractGameAction.AttackEffect.BLUNT_HEAVY));
                break;
            case 7: //二形态多段吸血 ATTACK_BUFF
                if (Settings.FAST_MODE) {
                    AbstractDungeon.actionManager.addToBottom(new VFXAction(new BloodShotEffect(this.hb.cX, this.hb.cY, AbstractDungeon.player.hb.cX, AbstractDungeon.player.hb.cY, 5), 0.25F));
                } else {
                    AbstractDungeon.actionManager.addToBottom(new VFXAction(new BloodShotEffect(this.hb.cX, this.hb.cY, AbstractDungeon.player.hb.cX, AbstractDungeon.player.hb.cY, 5), 0.6F));
                }
                for (int i=0;i<5;i++) {
                    addToBot(new DamageAction(AbstractDungeon.player, this.damage.get(2), AbstractGameAction.AttackEffect.BLUNT_HEAVY, true));
                    addToBot(new AbstractGameAction() {
                        @Override
                        public void update() {
                            addToTop(new HealAction(StrongerHeart.this, StrongerHeart.this, AbstractDungeon.player.lastDamageTaken * (AbstractDungeon.ascensionLevel >= 19 ? 3 : 2)));
                            isDone = true;
                        }
                    });
                }
                break;
            case 8: //三阶段重击 ATTACK_BUFF
                addToBot(new VFXAction(new ViceCrushEffect(AbstractDungeon.player.hb.cX, AbstractDungeon.player.hb.cY), 0.5F));
                addToBot(new DamageAction(AbstractDungeon.player, this.damage.get(3), AbstractGameAction.AttackEffect.BLUNT_HEAVY));
                addToBot(new ApplyPowerAction(this, this, new RitualPower(this, 1, false)));
                addToBot(new AbstractGameAction() {
                    @Override
                    public void update() {
                        if (AbstractDungeon.ascensionLevel >= 9) {
                            StrongerHeart.this.damage.get(3).base += 11;
                        } else {
                            StrongerHeart.this.damage.get(3).base += 10;
                        }
                        isDone = true;
                    }
                });
                break;
            case 9: //三阶段多段 ATTACK
                if (Settings.FAST_MODE) {
                    AbstractDungeon.actionManager.addToBottom(new VFXAction(new BloodShotEffect(this.hb.cX, this.hb.cY, AbstractDungeon.player.hb.cX, AbstractDungeon.player.hb.cY, phase3AttackAmount), 0.25F));
                } else {
                    AbstractDungeon.actionManager.addToBottom(new VFXAction(new BloodShotEffect(this.hb.cX, this.hb.cY, AbstractDungeon.player.hb.cX, AbstractDungeon.player.hb.cY, phase3AttackAmount), 0.6F));
                }
                for (int i=0;i<phase3AttackAmount;i++) {
                    addToBot(new DamageAction(AbstractDungeon.player, this.damage.get(4), AbstractGameAction.AttackEffect.BLUNT_HEAVY, true));
                }
                addToBot(new ApplyPowerAction(this, this, new BeatOfLifePower(this, 1)));
                phase3AttackAmount += 3;
                break;
        }
        addToBot(new RollMoveAction(this));
    }

    @Override
    protected void getMove(int aiRng) {
        if (turns == 0) {
            if (AbstractDungeon.ascensionLevel < 19) {
                this.setMove((byte)2, Intent.ATTACK_BUFF, this.damage.get(0).base);
            } else {
                this.setMove((byte)2, Intent.ATTACK_BUFF, this.damage.get(0).base, 10, true);
            }
        } else {
            if (this.lastMove((byte) 2)) {
                this.setMove((byte) 3, Intent.DEBUFF);
                return;
            } else if (this.lastMove((byte) 3)) {
                this.setMove((byte) 1, Intent.BUFF);
                return;
            }
            if (this.lastMove((byte) 1) || this.lastMove((byte) 0)) { //上次行动是强化或复活
                switch (this.phase) {
                    case 2:
                        this.setMove((byte) 4, Intent.STRONG_DEBUFF);
                        break;
                    case 3:
                    default:
                        this.setMove((byte) 8, Intent.ATTACK_BUFF, this.damage.get(3).base);
                        break;
                }
                return;
            }
            if (this.lastMove((byte) 4)) {
                if (aiRng < 50) {
                    this.setMove((byte) 5, Intent.DEFEND);
                } else {
                    this.setMove((byte) 6, Intent.ATTACK, this.damage.get(1).base);
                }
            } else if (this.lastMove((byte) 5) || this.lastMove((byte) 6)) {
                this.setMove(MOVES[0], (byte)7, Intent.ATTACK_BUFF, this.damage.get(2).base, 5, true);
            } else if (this.lastMove((byte) 7)) {
                this.setMove((byte) 1, Intent.BUFF);
            }
            if (this.lastMove((byte) 8)) {
                this.setMove(MOVES[1], (byte)9, Intent.ATTACK_BUFF, this.damage.get(4).base, phase3AttackAmount, true);
            } else if (this.lastMove((byte) 9)) {
                this.setMove((byte) 8, Intent.ATTACK_BUFF, this.damage.get(3).base);
            }
        }
        turns++;
    }

    @Override
    public void die() {
        if (!AbstractDungeon.getCurrRoom().cannotLose) {
            super.die();
            this.useFastShakeAnimation(5.0F);
            CardCrawlGame.screenShake.rumble(4.0F);

            this.onBossVictoryLogic();
            this.onFinalBossVictoryLogic();
        }
    }
}
